﻿
using Org.BouncyCastle.Crypto;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace System
{
    public static class ObjectExtensions
    {
        /// <summary>
        /// 常见数据类型的Null判断。null、DbNull、JsonNull
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsNull(this object obj)
        {
            if (obj == null)
            {
                return true;
            }

            if (obj is DBNull)
            {
                return true;
            }
            if (Convert.IsDBNull(obj))
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 将对象的属性复制到另一个对象的同名且同类型属性中
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        public static void CopyTo(this object obj1, object obj2)
        {
            if (obj1 == null)
            {
                throw new ArgumentNullException(nameof(obj1));
            }
            if (obj2 == null)
            {
                throw new ArgumentNullException(nameof(obj2));
            }
            var t1 = obj1.GetType();
            var t2 = obj2.GetType();

            IDictionary<string, object> dic1 = new Dictionary<string, object>();
            if (obj1 is IDictionary<string, object> dic)
            {
                dic1 = dic;
            }
            else
            {
                foreach (var p in t1.GetProperties())
                {
                    if (p.CanRead)
                    {
                        dic1.Add(p.Name, p.GetValue(obj1));
                    }

                }
            }

            var pis2 = t2.GetProperties();
            foreach (var p2 in pis2)
            {
                if (dic1.ContainsKey(p2.Name))
                {
                    if (p2.CanWrite)
                    {
                        p2.SetValue(obj2, dic1[p2.Name]);
                    }

                }
            }
        }
        /// <summary>
        /// 拷贝对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T Clone<T>(this T obj) where T : new()
        {
            if (typeof(ICloneable).IsAssignableFrom(typeof(T)))
            {
                return (T)((ICloneable)obj).Clone();
            }
            if (typeof(T).IsValueType)
            {//值类型直接返回
                return obj;
            }
            var obj2 = new T();
            obj.CopyTo(obj2);
            return obj2;
        }
        /// <summary>
        /// 拷贝一个数组到另一个，这两个数组可以是不同类型，会拷贝它们共同的属性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="array1"></param>
        /// <returns></returns>
        public static T2[] CloneAndCopy<T, T2>(this T[] array1) where T2 : new()
        {
            T2[] array2 = new T2[array1.Length];
            for (int i = 0; i < array1.Length; i++)
            {
                T2 obj2 = new T2();
                array1[i].CopyTo(obj2);
                array2[i] = obj2;
            }
            return array2;
        }
    }
}
